﻿/***************************************************************************
	Copyright (C) 2010 RapidWebDev Organization (Author: Eunge, Legal Name: Jian Liu, Email: eunge.liu@gmail.com)

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ***************************************************************************/

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using BaoJianSoft.Common;
using BaoJianSoft.Platform.Properties;

namespace BaoJianSoft.Platform
{
	/// <summary>
	/// Permission key formatter class.
	/// </summary>
	public static class PermissionValueManager
	{
		private static volatile IPermissionApi permissionApi;
		private static volatile IMembershipApi membershipApi;
		private static volatile IOrganizationApi organizationApi;
		private static volatile IAuthenticationContext authenticationContext;

		private static IPermissionApi PermissionApi
		{
			get
			{
				if (permissionApi == null)
					permissionApi = SpringContext.Current.GetObject<IPermissionApi>();

				return permissionApi;
			}
		}

		private static IMembershipApi MembershipApi
		{
			get
			{
				if (membershipApi == null)
					membershipApi = SpringContext.Current.GetObject<IMembershipApi>();

				return membershipApi;
			}
		}

		private static IOrganizationApi OrganizationApi
		{
			get
			{
				if (organizationApi == null)
					organizationApi = SpringContext.Current.GetObject<IOrganizationApi>();

				return organizationApi;
			}
		}

		private static IAuthenticationContext AuthenticationContext
		{
			get
			{
				if (authenticationContext == null)
					authenticationContext = SpringContext.Current.GetObject<IAuthenticationContext>();

				return authenticationContext;
			}
		}

		/// <summary>
		/// EveryOne means all authenticated users.
		/// </summary>
		public const string EVERYONE = "EveryOne";

		/// <summary>
		/// Anonymous means all users including unauthenticated users.
		/// </summary>
		public const string ANONYMOUS = "Anonymous";

		/// <summary>
		/// To check whether the user has the dynamic page permission.
		/// The method returns true if the user has the permission either "{permissionValue}" or "{permissionValue}.All".
		/// The design of dynamic page permission is, 
		/// {permissionValue} means the user has the permission to go to management page with query and grid panel and view the data detail panel;
		/// but "{permissionValue}.All" means the user has all permissions on a dynamic page.
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="permissionValue"></param>
		/// <returns></returns>
		public static bool HasDynamicPagePermission(Guid userId, string permissionValue)
		{
			List<string> permissionValues = new List<string>
			{
				permissionValue,
				string.Format(CultureInfo.InvariantCulture, "{0}.All", permissionValue)
			};

			return PermissionApi.HasPermission(userId, permissionValues);
		}

		/// <summary>
		/// To check whether the current login user has the dynamic page permission.
		/// The method returns true if the user has the permission either "{permissionValue}" or "{permissionValue}.All".
		/// The design of dynamic page permission is, 
		/// {permissionValue} means the user has the permission to go to management page with query and grid panel and view the data detail panel;
		/// but "{permissionValue}.All" means the user has all permissions on a dynamic page.
		/// </summary>
		/// <param name="permissionValue"></param>
		/// <returns></returns>
		public static bool HasDynamicPagePermission(string permissionValue)
		{
			List<string> permissionValues = new List<string>
			{
				permissionValue,
				string.Format(CultureInfo.InvariantCulture, "{0}.All", permissionValue)
			};

			return PermissionApi.HasPermission(AuthenticationContext.User.UserId, permissionValues);
		}

		/// <summary>
		/// Check whether the current user has permission on adding a new single entity in dynamic page.
		/// </summary>
		/// <param name="permissionValue"></param>
		/// <returns></returns>
		public static bool HasDynamicPageNewPermission(string permissionValue)
		{
			string newPermission = string.Format(CultureInfo.InvariantCulture, "{0}.New", permissionValue);
			string allPermission = string.Format(CultureInfo.InvariantCulture, "{0}.All", permissionValue);
			return PermissionApi.HasPermission(AuthenticationContext.User.UserId, new[] { newPermission, allPermission });
		}

		/// <summary>
		/// Check whether the current user has permission on single entity deletion in dynamic page.
		/// </summary>
		/// <param name="permissionValue"></param>
		/// <returns></returns>
		public static bool HasDynamicPageDeletePermission(string permissionValue)
		{
			string deletePermission = string.Format(CultureInfo.InvariantCulture, "{0}.Delete", permissionValue);
			string allPermission = string.Format(CultureInfo.InvariantCulture, "{0}.All", permissionValue);
			return PermissionApi.HasPermission(AuthenticationContext.User.UserId, new[] { deletePermission, allPermission });
		}

		/// <summary>
		/// Check whether the current user has permission on single entity update in dynamic page.
		/// </summary>
		/// <param name="permissionValue"></param>
		/// <returns></returns>
		public static bool HasDynamicPageUpdatePermission(string permissionValue)
		{
			string updatePermission = string.Format(CultureInfo.InvariantCulture, "{0}.Update", permissionValue);
			string allPermission = string.Format(CultureInfo.InvariantCulture, "{0}.All", permissionValue);
			return PermissionApi.HasPermission(AuthenticationContext.User.UserId, new[] { updatePermission, allPermission });
		}

		/// <summary>
		/// Make permission value for specified command argument in aggregate panel of dynamic page.
		/// </summary>
		/// <param name="permissionValue"></param>
		/// <param name="commandArgument"></param>
		/// <returns></returns>
		public static bool HasAggregatePermission(string permissionValue, string commandArgument)
		{
			List<string> permissionValues = new List<string>();
			if (!string.IsNullOrEmpty(commandArgument))
				permissionValues.AddRange(new[] 
				{ 
					string.Format(CultureInfo.InvariantCulture, "{0}.All", permissionValue), 
					string.Format(CultureInfo.InvariantCulture, "{0}.{1}", permissionValue, commandArgument) 
				});
			else
				permissionValues.Add(permissionValue);

			return PermissionApi.HasPermission(AuthenticationContext.User.UserId, permissionValues);
		}

		/// <summary>
		/// Check whether the user has permission to view specified data. <br/>
		/// If view data type equals to CommonData, the user must has permissions on "permissionValue", "permissionValue.All" or "permissionValue.View".<br/>
		/// If view data type equals to OrganizationProfile, the user should have viewable permission on the specified organization id (dataEntityId) by PermissionApi.FindViewableOrganizationIds(). <br/>
		/// If view data type equals to UserProfile, the user should have viewable permission on the organization of specified user id (dataEntityId) by PermissionApi.FindViewableOrganizationIds(). 
		/// </summary>
		/// <param name="permissionValue"></param>
		/// <param name="detailPanelPageRenderMode"></param>
		/// <returns></returns>
		public static bool HasDynamicPageViewPermission(string permissionValue, DetailPanelViewDataTypes detailPanelViewType, string dataEntityId)
		{
			List<string> permissionValues = new List<string>
			{ 
				permissionValue,
				string.Format(CultureInfo.InvariantCulture, "{0}.All", permissionValue),
				string.Format(CultureInfo.InvariantCulture, "{0}.View", permissionValue)
			};

			switch (detailPanelViewType)
			{
				case DetailPanelViewDataTypes.CommonData:
					return PermissionApi.HasPermission(AuthenticationContext.User.UserId, permissionValues);

				case DetailPanelViewDataTypes.OrganizationProfile:
					Guid orgId = ConvertDataEntityIdToGuid(dataEntityId);
					return OrganizationApi.GetOrganization(orgId) != null;

				case DetailPanelViewDataTypes.UserProfile:
					Guid userId = ConvertDataEntityIdToGuid(dataEntityId);
					return MembershipApi.Get(userId) != null;
			}

			throw new NotSupportedException(detailPanelViewType.ToString());
		}

		private static Guid ConvertDataEntityIdToGuid(string dataEntityId)
		{
			try
			{
				return new Guid(dataEntityId);
			}
			catch
			{
				throw new InvalidDataException(dataEntityId);
			}
		}
	}

	/// <summary>
	/// Detail panel page view data type. 
	/// </summary>
	public enum DetailPanelViewDataTypes
	{
		/// <summary>
		/// View common data
		/// </summary>
		CommonData = 0,

		/// <summary>
		/// View organization profile
		/// </summary>
		OrganizationProfile = 1,

		/// <summary>
		/// View user profile
		/// </summary>
		UserProfile = 2
	}
}

